import "dart:collection";

import "package:flutter/cupertino.dart";
import "package:flutter/foundation.dart";
import "package:flutter/material.dart";
import "package:flutter_vant_ui/src/themes/themes.dart";
import "package:flutter_vant_ui/src/utils/utils.dart";
import "package:logger/logger.dart";

part "widget_logger.dart";

part "widget_enums.dart";

part "widget_core.dart";

part "widget_core_c.dart";

part "widget_core_g.dart";

part "basic/widget_button.dart";

part "basic/widget_button_g.dart";

part "basic/widget_cell-group.dart";

part "basic/widget_cell-group_g.dart";

part "basic/widget_cell.dart";

part "basic/widget_cell_g.dart";

part "basic/widget_config-provider.dart";

part "basic/widget_icon.dart";

part "basic/widget_icon_g.dart";

part "basic/widget_image.dart";

part "basic/widget_image_g.dart";

part "basic/widget_layout.dart";

part "basic/widget_layout_g.dart";

part "basic/widget_overlay.dart";

part "basic/widget_popup.dart";

part "basic/widget_popup_g.dart";

part "basic/widget_space.dart";

part "basic/widget_space_g.dart";

part "basic/widget_toast.dart";

part "basic/widget_toast_g.dart";

part "form/widget_calendar.dart";

part "form/widget_calendar_g.dart";

part "form/widget_cascader.dart";

part "form/widget_cascader_g.dart";

part "form/widget_checkbox-group.dart";

part "form/widget_checkbox-group_g.dart";

part "form/widget_checkbox.dart";

part "form/widget_checkbox_g.dart";

part "form/widget_date-picker.dart";

part "form/widget_date-picker_g.dart";

part "form/widget_field.dart";

part "form/widget_field_c.dart";

part "form/widget_field_g.dart";

part "form/widget_form.dart";

part "form/widget_form-validation.dart";

part "form/widget_form_g.dart";

part "form/widget_number-keyboard.dart";

part "form/widget_number-keyboard_g.dart";

part "form/widget_password-input.dart";

part "form/widget_password-input_g.dart";

part "form/widget_picker.dart";

part "form/widget_picker_g.dart";

part "form/widget_picker-group.dart";

part "form/widget_picker-group_g.dart";

part "form/widget_radio-group.dart";

part "form/widget_radio-group_g.dart";

part "form/widget_radio.dart";

part "form/widget_radio_g.dart";

part "form/widget_rate.dart";

part "form/widget_rate_g.dart";

part "form/widget_search.dart";

part "form/widget_search_g.dart";

part "form/widget_slider.dart";

part "form/widget_slider_g.dart";

part "form/widget_signature.dart";

part "form/widget_signature_g.dart";

part "form/widget_stepper.dart";

part "form/widget_stepper_g.dart";

part "form/widget_switch.dart";

part "form/widget_switch_g.dart";

part "form/widget_time-picker.dart";

part "form/widget_time-picker_g.dart";

part "form/widget_upload.dart";

part "form/widget_upload_g.dart";

part "display/widget_tag.dart";

part "display/widget_tag_g.dart";

part "widget_rotation.dart";

const kVanIconFontFamily = "van-icon";

/// 自定义主题映射函数
typedef VanThemeCustomCssGetFn<T> = dynamic Function(BuildContext context, VanCssKey key);

/// 启用自定义
runVanApp(Widget widget, {VanThemeCustomCssGetFn? getCustomCssValue}) {
  return runApp(VanProvider(provide: VanAppData(getCustomCssValue: getCustomCssValue), child: widget));
}

@immutable
class VanAppData with VanProvide {
  final VanThemeCustomCssGetFn? getCustomCssValue;

  const VanAppData({this.getCustomCssValue});
}

const _vanCssKeyPrefixExtraOfDoc = "--van-doc-";
const _vanCssKeyPrefix = "--van-";

class VanCssKey {
  final String key;
  final bool extra;

  const VanCssKey._raw(this.key, {this.extra = false});

  static bool isExtraKey(String key) {
    return key.startsWith(_vanCssKeyPrefixExtraOfDoc) || !key.startsWith(_vanCssKeyPrefix);
  }

  VanCssKey(this.key) : extra = true {
    if (key.isEmpty) throw ArgumentError("argument key must not be empty.");
    if (!isExtraKey(key)) throw ArgumentError("argument key not be \"--van-\" start or use \"--van-doc-\" start.");
  }

  factory VanCssKey._auto(String key) => VanCssKey._raw(key, extra: isExtraKey(key));

  @override
  String toString() {
    return key;
  }

  @override
  bool operator ==(Object other) {
    if (other is String) return key == other;
    if (other is VanCssKey) return key == other.key;
    return false;
  }

  @override
  int get hashCode => key.hashCode;

  Color? toColor(BuildContext context, {double? opacity}) {
    var color = get<Color>(context);
    if (color == null) return color;
    if (opacity != null && opacity >= 0 && opacity < 1) color = color.withOpacity(opacity);
    return color;
  }

  VanBgColor? toBgColor(BuildContext context) {
    return get<VanBgColor>(context);
  }

  Gradient? toGradient(BuildContext context) => get<Gradient>(context);

  EdgeInsets? toEdgeInsets(BuildContext context) => get<EdgeInsets>(context);

  BorderRadius? toBorderRadius(BuildContext context) => get<BorderRadius>(context);

  String? toStr(BuildContext context) => get<String>(context);

  double? toDouble(BuildContext context) => get<double>(context);

  int? toInt(BuildContext context) => get<int>(context);

  T? get<T>(BuildContext context) {
    if (extra) {
      final getCustomCssValue = VanProvider.of<VanAppData>(context)?.getCustomCssValue;
      if (getCustomCssValue != null) return _resolve<T>(getCustomCssValue(context, this));
      debugPrint("please use provide runVanThemeCustomApp argument getCustomCssValue.");
      return null;
    }

    if (VanButtonTheme.support(this)) return _resolve<T>(VanButtonTheme.get(context, key: this));
    if (VanCellGroupTheme.support(this)) return _resolve<T>(VanCellGroupTheme.get(context, key: this));
    if (VanCellTheme.support(this)) return _resolve<T>(VanCellTheme.get(context, key: this));
    if (VanImageTheme.support(this)) return _resolve<T>(VanImageTheme.get(context, key: this));
    if (VanPopupTheme.support(this)) return _resolve<T>(VanPopupTheme.get(context, key: this));

    if (VanCheckboxTheme.support(this)) return _resolve<T>(VanCheckboxTheme.get(context, key: this));
    if (VanFieldTheme.support(this)) return _resolve<T>(VanFieldTheme.get(context, key: this));
    if (VanRadioTheme.support(this)) return _resolve<T>(VanRadioTheme.get(context, key: this));
    if (VanSwitchTheme.support(this)) return _resolve<T>(VanSwitchTheme.get(context, key: this));

    //
    if (VanTagTheme.support(this)) return _resolve<T>(VanTagTheme.get(context, key: this));
    return _resolve<T>(VanRootThemeData.get(context, key: this));
  }

  _resolve<T>(dynamic value) {
    if (value == null || T == dynamic) return value;
    if (value is T) return value;
    return VanCss._getValueWithType<T>(value);
  }
}
